<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
    

    

    



    <meta charset="utf-8">
    
    
    
    <title>RabbitMQ基本概念 | 奔跑的蜗牛 | 虚心若愚</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <meta name="theme-color" content="#3F51B5">
    
    
    <meta name="keywords" content="RabbitMQ">
    <meta name="description" content="转自1：http://www.ostest.cn/archives/497转自2：http://blog.csdn.net/whycold/article/details/41119807 一、使用场景 两个或多个系统间通过定时任务来同步某些数据。 异构系统的不同进程间相互调用、通讯的问题。  消息服务擅长于解决多系统、异构系统间的数据交换（消息通知/通讯）问题，你也可以把它用户系统间服务的相互调">
<meta name="keywords" content="RabbitMQ">
<meta property="og:type" content="article">
<meta property="og:title" content="RabbitMQ基本概念">
<meta property="og:url" content="http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/index.html">
<meta property="og:site_name" content="奔跑的蜗牛">
<meta property="og:description" content="转自1：http://www.ostest.cn/archives/497转自2：http://blog.csdn.net/whycold/article/details/41119807 一、使用场景 两个或多个系统间通过定时任务来同步某些数据。 异构系统的不同进程间相互调用、通讯的问题。  消息服务擅长于解决多系统、异构系统间的数据交换（消息通知/通讯）问题，你也可以把它用户系统间服务的相互调">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/queue.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/qq.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/2014-2-21-9-46-43.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/prefetch%20count.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/exchange.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/binding-1.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/fanout.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/direct.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/topic.png">
<meta property="og:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/prc.png">
<meta property="og:updated_time" content="2020-03-18T04:06:28.064Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="RabbitMQ基本概念">
<meta name="twitter:description" content="转自1：http://www.ostest.cn/archives/497转自2：http://blog.csdn.net/whycold/article/details/41119807 一、使用场景 两个或多个系统间通过定时任务来同步某些数据。 异构系统的不同进程间相互调用、通讯的问题。  消息服务擅长于解决多系统、异构系统间的数据交换（消息通知/通讯）问题，你也可以把它用户系统间服务的相互调">
<meta name="twitter:image" content="http://windynature.oschina.io/blog/2017/04/01/java/rabbitmq基本概念/queue.png">
    
        <link rel="alternative" href="/atom.xml" title="奔跑的蜗牛" type="application/atom+xml">
    
    <link rel="shortcut icon" href="/blog/favicon.ico">
    <link rel="stylesheet" href="//unpkg.com/hexo-theme-material-indigo@1.5.2/css/style.css">
    <script>window.lazyScripts=[]</script>
</head>

<body>
    <div id="loading" class="active"></div>

    <aside id="menu" class="hide" >
  <div class="inner flex-row-vertical">
    <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menu-off">
        <i class="icon icon-lg icon-close"></i>
    </a>
    <div class="brand-wrap" style="background-image:url(/blog/img/timg.jpg)">
      <div class="brand">
        <a href="/blog/" class="avatar waves-effect waves-circle waves-light">
          <img src="/blog/img/user2.jpg">
        </a>
        <hgroup class="introduce">
          <h5 class="nickname">windy</h5>
          <a href="mailto:windynature@163.com" title="windynature@163.com" class="mail">windynature@163.com</a>
        </hgroup>
      </div>
    </div>
    <div class="scroll-wrap flex-col">
      <ul class="nav">
        
            <li class="waves-block waves-effect">
              <a href="/blog/"  >
                <i class="icon icon-lg icon-home"></i>
                主页
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/archives"  >
                <i class="icon icon-lg icon-archives"></i>
                归档
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/tags"  >
                <i class="icon icon-lg icon-tags"></i>
                标签
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/categories"  >
                <i class="icon icon-lg icon-th-list"></i>
                分类
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://github.com/WindyNature" target="_blank" >
                <i class="icon icon-lg icon-github"></i>
                Github
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://git.oschina.net/windynature" target="_blank" >
                <i class="icon icon-lg icon-mayun"></i>
                码云
              </a>
            </li>
        
      </ul>
    </div>
  </div>
</aside>

    <main id="main">
        <header class="top-header" id="header">
    <div class="flex-row">
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light on" id="menu-toggle">
          <i class="icon icon-lg icon-navicon"></i>
        </a>
        <div class="flex-col header-title ellipsis">RabbitMQ基本概念</div>
        
        <div class="search-wrap" id="search-wrap">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
                <i class="icon icon-lg icon-chevron-left"></i>
            </a>
            <input type="text" id="key" class="search-input" autocomplete="off" placeholder="输入感兴趣的关键字">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="search">
                <i class="icon icon-lg icon-search"></i>
            </a>
        </div>
        
        
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menuShare">
            <i class="icon icon-lg icon-share-alt"></i>
        </a>
        
    </div>
</header>
<header class="content-header post-header">

    <div class="container fade-scale">
        <h1 class="title">RabbitMQ基本概念</h1>
        <h5 class="subtitle">
            
                <time datetime="2017-04-01T13:05:48.000Z" itemprop="datePublished" class="page-time">
  2017-04-01
</time>


	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/消息队列/">消息队列</a></li></ul>

            
        </h5>
    </div>

    

</header>


<div class="container body-wrap">
    
    <aside class="post-widget">
        <nav class="post-toc-wrap" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#一、使用场景"><span class="post-toc-text">一、使用场景</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#二、RabbitMQ简介"><span class="post-toc-text">二、RabbitMQ简介</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#1-AMQP"><span class="post-toc-text">1. AMQP</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-RabbitMQ"><span class="post-toc-text">2. RabbitMQ</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#三、RabbitMQ中的概念"><span class="post-toc-text">三、RabbitMQ中的概念</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#1-ConnectionFactory、Connection、Channel"><span class="post-toc-text">1. ConnectionFactory、Connection、Channel</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-Queue"><span class="post-toc-text">2. Queue</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#3-Message-Acknowledgment"><span class="post-toc-text">3. Message Acknowledgment</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#4-Message-durability"><span class="post-toc-text">4. Message durability</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#5-Prefetch-count"><span class="post-toc-text">5. Prefetch count</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#6-Exchange"><span class="post-toc-text">6. Exchange</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#6-1-routing-key"><span class="post-toc-text">6.1. routing key</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#6-2-Binding"><span class="post-toc-text">6.2. Binding</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#6-4-Exchange-Types"><span class="post-toc-text">6.4 Exchange Types</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#1-fanout"><span class="post-toc-text">1. fanout</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#2-direct"><span class="post-toc-text">2. direct</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#3-topic"><span class="post-toc-text">3. topic</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#4-headers"><span class="post-toc-text">4. headers</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#5-RPC"><span class="post-toc-text">5. RPC</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#7-虚拟主机-virtual-host"><span class="post-toc-text">7. 虚拟主机(virtual host)</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#8-几个概念"><span class="post-toc-text">8. 几个概念</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#9-为什么使用Channel，而不是直接使用TCP连接"><span class="post-toc-text">9. 为什么使用Channel，而不是直接使用TCP连接</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#10-消息队列使用过程"><span class="post-toc-text">10. 消息队列使用过程</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#RabbitMQ的优点"><span class="post-toc-text">RabbitMQ的优点</span></a></li></ol></li></ol>
        </nav>
    </aside>
    
<article id="post-java/rabbitmq基本概念"
  class="post-article article-type-post fade" itemprop="blogPost">

    <div class="post-card">
        <h1 class="post-card-title">RabbitMQ基本概念</h1>
        <div class="post-meta">
            <time class="post-time" title="2017年04月01日 21:05" datetime="2017-04-01T13:05:48.000Z"  itemprop="datePublished">2017-04-01</time>

            
	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/消息队列/">消息队列</a></li></ul>



            
<span id="busuanzi_container_page_pv" title="文章总阅读量" style='display:none'>
    <i class="icon icon-eye icon-pr"></i><span id="busuanzi_value_page_pv"></span>
</span>


            

        </div>
        <div class="post-content" id="post-content" itemprop="postContent">
            <p><a href="http://www.ostest.cn/archives/497" target="_blank" rel="noopener">转自1：http://www.ostest.cn/archives/497</a><br><a href="http://blog.csdn.net/whycold/article/details/41119807" target="_blank" rel="noopener">转自2：http://blog.csdn.net/whycold/article/details/41119807</a></p>
<h1 id="一、使用场景"><a href="#一、使用场景" class="headerlink" title="一、使用场景"></a>一、使用场景</h1><ul>
<li>两个或多个系统间通过定时任务来同步某些数据。</li>
<li>异构系统的不同进程间相互调用、通讯的问题。</li>
</ul>
<p>消息服务擅长于解决多系统、异构系统间的数据交换（消息通知/通讯）问题，你也可以把它用户系统间服务的相互调用（RPC）。</p>
<h1 id="二、RabbitMQ简介"><a href="#二、RabbitMQ简介" class="headerlink" title="二、RabbitMQ简介"></a>二、RabbitMQ简介</h1><h2 id="1-AMQP"><a href="#1-AMQP" class="headerlink" title="1. AMQP"></a>1. AMQP</h2><p><strong><code>AMQP</code></strong>:(Advanced Message Queuing Protocol，高级消息队列协议)，是应用层协议的一个<code>开放标准</code>，为面向消息的中间件设计。消息中间件主要用于组件之间的解耦，消息的发送者无需知道消息使用者的存在，反之亦然。<br>AMQP的主要特征是：<code>面向消息、队列、路由（包括点对点和发布/订阅）、可靠性、安全。</code></p>
<h2 id="2-RabbitMQ"><a href="#2-RabbitMQ" class="headerlink" title="2. RabbitMQ"></a>2. RabbitMQ</h2><p><strong><code>RabbitMQ</code></strong>的主要特征是一个开源的<code>AMQP</code>实现，服务器端使用<code>Erlang</code>语言编写，支持多种客户端，如：Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等，支持AJAX。用户在<code>分布式系统</code>中存储转发消息，在易用性、扩展性、高可用性等方面表现不俗。</p>
<h1 id="三、RabbitMQ中的概念"><a href="#三、RabbitMQ中的概念" class="headerlink" title="三、RabbitMQ中的概念"></a>三、RabbitMQ中的概念</h1><h2 id="1-ConnectionFactory、Connection、Channel"><a href="#1-ConnectionFactory、Connection、Channel" class="headerlink" title="1. ConnectionFactory、Connection、Channel"></a>1. ConnectionFactory、Connection、Channel</h2><p>ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。</p>
<ul>
<li><strong><code>Connection</code></strong>：是RabbitMQ的socket连接，它封装了socket协议相关部分逻辑。</li>
<li><strong><code>ConnectionFactory</code></strong>：为<code>Connection</code>的制造工厂。</li>
<li><strong><code>Channel</code></strong>：是我们与RabbitMQ打交道的最重要的一个接口，我们大部分的业务操作是在<code>Channel</code>这个接口中完成的，包括<code>定义Queue</code>、<code>定义Exchange</code>、<code>绑定Queue</code>、<code>发布消息</code>等。 </li>
</ul>
<h2 id="2-Queue"><a href="#2-Queue" class="headerlink" title="2. Queue"></a>2. Queue</h2><p>队列(queue):是由消费者简历的，是messages的重点，可以理解成装消息的容器。消息一直存在队列里，知道有客户点或者成为<code>Consumer</code>消费者连接到这个队列并将message取走位置。队列可以有多个。<br>Queue是RabbitMQ的内部对象，用于存储消息，用下图表示。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/queue.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure></center>

<p>RabbitMQ中的消息都只能存储在<code>Queue</code>中，生产者（下图中的P）生产消息并最终投递到Queue中，消费者（下图中的C）可以从<code>Queue</code>中获取消息并消费。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/qq.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>

</center>

<p>多个消费者可以订阅同一个Queue，这时Queue中的消息会被平均分摊给多个消费者进行处理，而不是每个消费者都收到所有的消息并处理。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/2014-2-21-9-46-43.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<h2 id="3-Message-Acknowledgment"><a href="#3-Message-Acknowledgment" class="headerlink" title="3. Message Acknowledgment"></a>3. Message Acknowledgment</h2><p>在实际应用中，可能会发生消费者收到Queue中的消息，但没有处理完成就宕机（或者出现其他意外）的情况，这种情况下就可能导致消息丢失。为了避免这种情况发生，我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ，RabbitMQ收到消息回执（Message acknowledgement）后才降该消息从Queue中移除；如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开，则RabbitMQ会将消息发送给其他消费者（如果存在多个消费者）进行处理。这里不存在timeout概念，一个消费者处理消息时间再长也不会导致该消息被发送个其他消费者，除非它的RabbitMQ连接断开。<br>这里会产生另外一个问题，如果我们的开发人员在处理完业务逻辑后，忘记发送回执给RabbitMQ，这将会导致严重的bug-Queue中堆积的消息会越来越多；消费者重启后会重复消费这些消息并重复执行业务逻辑。<br>另外pub message是没有ack的。</p>
<h2 id="4-Message-durability"><a href="#4-Message-durability" class="headerlink" title="4. Message durability"></a>4. Message durability</h2><p>如果我们希望即使在RabbitMQ服务重启的情况下，也不会丢失消息，我们可以将Queue与Message都设置为可持久化的（durable），这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。但依然解决不了小概率丢失时间的发生（比如RabbitMQ 服务器已经收到生产者的消息，但还没有来得及持久化该消息时RabbitMQ服务器就断电了），如果我们需要对这种小概率事件也要管理起来，那么我们要用到<code>事务</code>。</p>
<h2 id="5-Prefetch-count"><a href="#5-Prefetch-count" class="headerlink" title="5. Prefetch count"></a>5. Prefetch count</h2><p>前面我们讲到如果有多个消费者同事订阅同一个Queue中的消息，Queue中的消息平坦给多个消费者。这时如果每个消息的处理时间不同，就有可能会导致某些消费者一直在忙，而另外一些消费者很快就会处理完手头工作并一直空闲的情况。我们可以通过设置<code>prefetchCount</code>来限制Queue每次发送给每个消费者的消息数量，比如我们设置<code>prefetchCount = 1</code>，则Queue<code>每次给每个</code>消费者<code>发送一条消息</code>；消费者<code>处理完</code>这条消息后Queue会<code>再给该消费者发送</code>一条消息。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/prefetch%20count.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<h2 id="6-Exchange"><a href="#6-Exchange" class="headerlink" title="6. Exchange"></a>6. Exchange</h2><p>交换机：可以理解成具有路由表的路由程序。每个消息都有一个路由键(routing key)，就是一个简单的字符串。交换机中有一系列的绑定(bingding)，即路由规则(routes)。交换机可以有多个。多个队列可以和同一个交换机绑定，同时多个交换机也可以和同一个队列绑定。(多对多的关系)</p>
<p>在上一节我们看到生产者将消息投递到Queue中，实际上这在RabbitMQ中是永远不会发生的。实际的情况是，生产者将消息发送到Exchange，由Exchange将消息路由到一个或多个Queue中（或者丢弃）。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/exchange.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<p>Exchange是按照什么逻辑将消息路由到Queue的？这个将在<code>Binding</code>一节介绍。<br>RabbitMQ中的Exchange有<code>四种类型</code>，不同的类型有着不同的路由策略，这将在Exchange Types一节介绍。</p>
<h3 id="6-1-routing-key"><a href="#6-1-routing-key" class="headerlink" title="6.1. routing key"></a>6.1. routing key</h3><p><strong>生产者在将消息发送给Exchange的时候，一般会指定一个<code>routing key</code>，来指定消息的路由规则，而这个routing key需要与<code>Exchange Type</code>及<code>binding key</code>联合使用才能最终生效。</strong></p>
<p>在<code>Exchange Type</code>与<code>binding key</code>固定的情况下（在正常使用时，一般这些内容都是固定配置好的），我们的生产者就可以在发送消息给Exchange时，通过指定<code>routing key</code>来决定消息流向哪里。</p>
<p><strong>RabbitMQ为routing key设定的长度限制为255 bytes。</strong></p>
<h3 id="6-2-Binding"><a href="#6-2-Binding" class="headerlink" title="6.2. Binding"></a>6.2. Binding</h3><p>RabbitMQ中通过Binding将Exchange与Queue关联起来，这样RabbitMQ就知道如何正确地将消息路由到指定的Queue了。<br><center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/binding-1.png" alt="binding" title>
                </div>
                <div class="image-caption">binding</div>
            </figure></center></p>

### 6.3 Binding key

<p>在绑定（<code>Binding</code>）Exchange与Queue的同时，一般会指定一个binding key；消费者将消息发送给Exchange时，一般会指定一个routing key；当binding key与routing key相匹配时，消息将会被路由到对应的Queue中。这个将在Exchange Types章节会列举实际的例子加以说明。<br>在绑定多个Queue到同一个Exchange的时候，这些Binding允许使用相同的binding key。<br>binding key 并不是在所有情况下都生效，它依赖于Exchange Type，比如fanout类型的Exchange就会无视binding key，而是将消息路由到所有绑定到该Exchange的Queue。</p>
<h3 id="6-4-Exchange-Types"><a href="#6-4-Exchange-Types" class="headerlink" title="6.4 Exchange Types"></a>6.4 Exchange Types</h3><p>RabbitMQ常用的Exchange Type有<code>fanout、direct、topic、headers</code>这四种（AMQP规范里还提到两种Exchange Type，分别为system与自定义，这里不予以描述），下面分别进行介绍。</p>
<h4 id="1-fanout"><a href="#1-fanout" class="headerlink" title="1. fanout"></a>1. fanout</h4><p>fanout类型的Exchange路由规则非常简单，它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中（<code>类似广播</code>）。</p>
<center>
<figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/fanout.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<p>上图中，生产者（P）发送到Exchange（X）的所有消息都<code>会路由到图中的两个Queue</code>，并最终被两个消费者（C1与C2）消费。</p>
<h4 id="2-direct"><a href="#2-direct" class="headerlink" title="2. direct"></a>2. direct</h4><p>direct类型的Exchange路由规则也很简单，它会把消息路由到那些binding key与routing key<code>完全匹配</code>的Queue中。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/direct.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<p>以上图的配置为例，我们以<code>routingKey=”error”</code>发送消息到Exchange，则消息会路由到Queue1（amqp.gen-S9b…，这是由RabbitMQ自动生成的Queue名称）和Queue2（amqp.gen-Agl…）；如果我们以routingKey=”info”或routingKey=”warning”来发送消息，则消息只会路由到Queue2。如果我们以其他routingKey发送消息，则消息不会路由到这两个Queue中。</p>
<h4 id="3-topic"><a href="#3-topic" class="headerlink" title="3. topic"></a>3. topic</h4><p>前面讲到direct类型的Exchange路由规则是<code>完全匹配</code>binding key与routing key，但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展，它与direct类型的Exchage相似，也是将消息路由到binding key与routing key相匹配的Queue中，但这里的匹配规则有些不同(<code>通配符</code>)，它约定：</p>
<ul>
<li>routing key为一个句点号“. ”分隔的字符串（我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词），如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”</li>
<li>binding key与routing key一样也是句点号“. ”分隔的字符串</li>
<li>binding key中可以存在两种特殊字符“*”与“#”，用于做<code>模糊匹配</code>，其中<code>“*”用于匹配一个单词</code>，<code>“#”用于匹配多个单词（可以是零个）</code></li>
</ul>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/topic.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<p>以上图中的配置为例，routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2，routingKey=”lazy.orange.fox”的消息会路由到Q1与Q2，routingKey=”lazy.brown.fox”的消息会路由到Q2，routingKey=”lazy.pink.rabbit”的消息会路由到Q2（只会投递给Q2一次，虽然这个routingKey与Q2的两个bindingKey都匹配）；routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃，因为它们没有匹配任何bindingKey。</p>
<h4 id="4-headers"><a href="#4-headers" class="headerlink" title="4. headers"></a>4. headers</h4><p>headers类型的Exchange<code>不依赖于 routing key与binding key</code>的匹配规则来路由消息，而是根据发送的消息内容中的headers属性进行匹配。</p>
<p>在绑定Queue与Exchange时<code>指定一组键值对</code>，当消息发送到Exchange时，RabbitMQ会渠道该消息的headers（也是一个键值对的形式），对比其中的键值对是否完全匹配Queue与Exchange绑定石指定的键值对。如果完全匹配则消息会路由到该Queue，否则不会路由到该Queue。</p>
<h4 id="5-RPC"><a href="#5-RPC" class="headerlink" title="5. RPC"></a>5. RPC</h4><p>MQ本身是基于异步的消息处理，前面的示例中所有的生产者（P）将消息发送到<code>RabbitMQ</code>后不会知道消费者（C）处理成功或者失败（甚至连有没有消费者来处理这条消息都不知道）。<br>但知己的应用场景中，我们很可能需要到一些同步处理，需要同步等待服务端将我们的消息处理完成后再进行下一步处理。这相当于RPC。在RabbitMQ中也支持RPC。</p>
<center><figure class="image-bubble">
                <div class="img-lightbox">
                    <div class="overlay"></div>
                    <img src="/blog/2017/04/01/java/rabbitmq基本概念/prc.png" alt title>
                </div>
                <div class="image-caption"></div>
            </figure>
</center>

<p>RabbitMQ中实现RPC的机制是：</p>
<ul>
<li>客户端发送请求（消息）时，在消息的属性（MessageProperties，在AMQP秀一种定义了14种properties，这些属性会随着消息一起发送）中设置了两个值<code>replyTo</code>(一个Queue名称，用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和<code>correlationId</code>（此次请求的标志号，服务器处理完成后需要将此属性返回，客户端将根据这个id了解哪条请求被成功执行了或执行失败）。</li>
<li>服务器端收到消息并处理</li>
<li>服务器端处理完消息后，并将生成一条应答消息到replayTo指定的Queue，同时带上correlationId属性</li>
<li>客户端之前已经订阅replayTo指定的Queue，从中收到服务器的应答消息后，根据其中的correlationId属性分析哪条请求被执行了，根据执行结果进行后续业务处理。</li>
</ul>
<h2 id="7-虚拟主机-virtual-host"><a href="#7-虚拟主机-virtual-host" class="headerlink" title="7. 虚拟主机(virtual host)"></a>7. 虚拟主机(virtual host)</h2><p>一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢？RabbitMQ中，<strong><code>用户只能在虚拟主机的力度进行权限控制</code></strong>。因此，如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbicMQ服务器都有一个默认的虚拟主机”/“。</p>
<h2 id="8-几个概念"><a href="#8-几个概念" class="headerlink" title="8. 几个概念"></a>8. 几个概念</h2><ul>
<li>Borker:简单来说就是消息队列服务器实体，一个broker中可开设多个多个vhost，用作不同用户的权限分离。</li>
<li>Exchange:消息交换机，它指定消息按照什么规则，路由到哪个队列。</li>
<li>Queue:消息队列载体，每个消息都会被投入到一个或多个队列。</li>
<li>Binding:绑定，它的作用是把exchange和Queue按照路由规则绑定起来。</li>
<li>Routing key:路由关键字，exchange根据这个关键字进行消息投递。</li>
<li>vhost:虚拟主机，一个broker可以开设多个vhost，用作不同用户的权限分离</li>
<li>producer:消息生产者，就是投递消息的程序。</li>
<li>consumer:消息消费者，就是接受消息的程序。</li>
<li>channel:消息通道，在客户端的每个连接里，可建立多个channel，每个channel代表一个会话任务。</li>
<li>connection:就是一个TCP连接。Producer和Consumer都是通过TCP连接到RabbitMQ Server的。</li>
<li>Channels:虚连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说，一般情况是程序建立TCP连接，第二部就是建立这个Channel。</li>
</ul>
<h2 id="9-为什么使用Channel，而不是直接使用TCP连接"><a href="#9-为什么使用Channel，而不是直接使用TCP连接" class="headerlink" title="9. 为什么使用Channel，而不是直接使用TCP连接"></a>9. 为什么使用Channel，而不是直接使用TCP连接</h2><p>对于OS来说，建立和关闭连接是由代价的，频繁的建立关闭TCP连接对于系统性能有很大的影响，而且TCP的连接数也有限制，这页限制了系统处理高并发的能力。但是，在TCP连接中建立Channel是没有上述代价的。对于Producer或者Consumer来说，可以并发的使用多个Channel进行Publish或者Receive。有实验表明，1s的数据可以Publish10K的数据包。淡然对于不同的硬件环境，不同的数据包大小这个数据肯定不一样。</p>
<h2 id="10-消息队列使用过程"><a href="#10-消息队列使用过程" class="headerlink" title="10. 消息队列使用过程"></a>10. 消息队列使用过程</h2><ol>
<li>客户端连接到消息队列服务器，打开一个Channel。</li>
<li>客户端声明一个excheange，并设置相关属性。</li>
<li>客户点声明一个queue，并设置相关属性。</li>
<li>客户端使用routing key，在exchange和queue之间建立好绑定关系。</li>
<li>客户端投递消息到exchange。</li>
<li>exchange收到消息后，就根据消息的key和已经设置的binding，进行消息路由，将消息路由投递到一个或多个队列里。</li>
</ol>
<h2 id="RabbitMQ的优点"><a href="#RabbitMQ的优点" class="headerlink" title="RabbitMQ的优点"></a>RabbitMQ的优点</h2><ol>
<li>基于erlang语言开发具有高可用高并发的优点，适合集群服务器。</li>
<li>健壮、稳定、易用、跨平台、支持多种语言、文档齐全。</li>
<li>有消息确认机制和持久化机制，可靠性高。</li>
<li>开源</li>
</ol>
<p>其他MQ的优势：</p>
<ol>
<li>Apache ActiveMQ曝光率最高，但是可能会丢消息。</li>
<li>ZeroMQ延迟很低、支持灵活拓扑，但是不支持消息持久化和崩溃恢复。</li>
</ol>

        </div>

        <blockquote class="post-copyright">
    <div class="content">
        
<span class="post-time">
    最后更新时间：<time datetime="2020-03-18T04:06:28.064Z" itemprop="dateUpdated">2020年3月18日 12:06</time>
</span><br>


        这里写留言或版权声明：<a href="/blog/2017/04/01/java/rabbitmq基本概念/" target="_blank" rel="external">http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/</a>
    </div>
    <footer>
        <a href="http://windynature.oschina.io">
            <img src="/blog/img/user2.jpg" alt="windy">
            windy
        </a>
    </footer>
</blockquote>

        


        <div class="post-footer">
            
	<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/blog/tags/RabbitMQ/">RabbitMQ</a></li></ul>


            
<div class="page-share-wrap">
    

<div class="page-share" id="pageShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&title=《RabbitMQ基本概念》 — 奔跑的蜗牛&pic=http://windynature.oschina.io/img/user2.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&title=《RabbitMQ基本概念》 — 奔跑的蜗牛&source=" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《RabbitMQ基本概念》 — 奔跑的蜗牛&url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&via=http://windynature.oschina.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>



    <a href="javascript:;" id="shareFab" class="page-share-fab waves-effect waves-circle">
        <i class="icon icon-share-alt icon-lg"></i>
    </a>
</div>



        </div>
    </div>

    
<nav class="post-nav flex-row flex-justify-between">
  
    <div class="waves-block waves-effect prev">
      <a href="/blog/2017/04/03/设计模式/装饰模式/" id="post-prev" class="post-nav-link">
        <div class="tips"><i class="icon icon-angle-left icon-lg icon-pr"></i> Prev</div>
        <h4 class="title">装饰模式总结</h4>
      </a>
    </div>
  

  
    <div class="waves-block waves-effect next">
      <a href="/blog/2017/02/13/java/类加载机制与反射/" id="post-next" class="post-nav-link">
        <div class="tips">Next <i class="icon icon-angle-right icon-lg icon-pl"></i></div>
        <h4 class="title">类加载机制和反射</h4>
      </a>
    </div>
  
</nav>



    

<div class="comments" id="comments">
    <div class="ds-thread" data-thread-key="java/rabbitmq基本概念" data-title="RabbitMQ基本概念" data-url="http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/"></div>
</div>
<script>
lazyScripts.push('//cdn.bootcss.com/marked/0.3.6/marked.min.js');

var duoshuoQuery = {short_name:'ysblog', theme: 'none'};
lazyScripts.push('//unpkg.com/hexo-theme-material-indigo@1.5.2/js/embed.min.js');


</script>










</article>



</div>

        <footer class="footer">
    <div class="top">
        
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        站点总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        站点总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


        <p>
            <span><a href="/atom.xml" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>
            <span>博客内容遵循 <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0协议</a></span>
        </p>
    </div>
    <div class="bottom">
        <p>
            <span>Power by <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/yscoder/hexo-theme-indigo" target="_blank">indigo</a></span>
            <span>奔跑的蜗牛 &copy; 2015 - 2020</span>
        </p>
    </div>
</footer>

    </main>
    <div class="mask" id="mask"></div>
<a href="javascript:;" id="gotop" class="waves-effect waves-circle waves-light"><span class="icon icon-lg icon-chevron-up"></span></a>



<div class="global-share" id="globalShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&title=《RabbitMQ基本概念》 — 奔跑的蜗牛&pic=http://windynature.oschina.io/img/user2.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&title=《RabbitMQ基本概念》 — 奔跑的蜗牛&source=" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《RabbitMQ基本概念》 — 奔跑的蜗牛&url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/&via=http://windynature.oschina.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://windynature.oschina.io/2017/04/01/java/rabbitmq基本概念/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>


<div class="page-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <p>扫一扫，分享到微信</p>
    <img src="" alt="微信分享二维码">
</div>




    <script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>
<script>
var BLOG = { ROOT: '/blog/', SHARE: true, REWARD: false };



</script>

<script src="//unpkg.com/hexo-theme-material-indigo@1.5.2/js/main.min.js"></script>


<div class="search-panel" id="search-panel">
    <ul class="search-result" id="search-result"></ul>
</div>
<template id="search-tpl">
<li class="item">
    <a href="{path}" class="waves-block waves-effect">
        <div class="title ellipsis" title="{title}">{title}</div>
        <div class="flex-row flex-middle">
            <div class="tags ellipsis">
                {tags}
            </div>
            <time class="flex-col time">{date}</time>
        </div>
    </a>
</li>
</template>

<script src="//unpkg.com/hexo-theme-material-indigo@1.5.2/js/search.min.js" async></script>






<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>





</body>
</html>
